package com.autonavi.yunda.yunji.common.utils;

import com.autonavi.yunda.yunji.common.exception.AmapException;
import com.autonavi.yunda.yunji.common.exception.AmapExceptionCode;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;

import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;

public class JsonUtils {
    private static final JsonConverter ENABLE_LOGGING_CONVERTER = new JsonConverter(true);
    private static final JsonConverter DISABLE_LOGGING_CONVERTER = new JsonConverter(false);
    private static JsonConverter converter = ENABLE_LOGGING_CONVERTER;

    public static void disableLogging() {
        converter = DISABLE_LOGGING_CONVERTER;
    }

    public static void enableLogging() {
        converter = ENABLE_LOGGING_CONVERTER;
    }

    public static ObjectNode createObjectNode() {
        return converter.createObjectNode();
    }

    public static <M> M from(String value, Class<M> clazz) {
        return converter.from(value, clazz);
    }

    public static <M> M from(String value, TypeReference<M> clazz) {
        return converter.from(value, clazz);
    }

    public static <M> M from(String value, JavaType type) {
        return converter.from(value, type);
    }

    public static <M> M from(String value, Type type) {
        if (value == null) {
            return null;
        }
        return converter.from(value, type);
    }

    public static <M> M fromOrException(String value, TypeReference<M> clazz) {
        return converter.fromOrException(value, clazz);
    }

    public static <M> M fromOrException(String value, Class<M> clazz) {
        return converter.fromOrException(value, clazz);
    }

    public static <M> M fromOrException(String value, JavaType type) {
        return converter.fromOrException(value, type);
    }

    public static <M> M convertOrException(Object value, Class<M> clazz) {
        return converter.convert(value, clazz);
    }

    public static <M> M convertOrException(Object value, TypeReference<M> clazz) {
        return converter.convert(value, clazz);
    }

    public static String toString(Object obj) {
        return converter.to(obj);
    }

    public static void buildJson(Map<String, Object> map, String path, Object value) {
        int idx = path.indexOf('.');
        if (idx > 0) {
            String key = path.substring(0, idx);
            if (map.containsKey(key)) {
                buildJson((Map<String, Object>) map.get(key), path.substring(idx + 1), value);
            } else {
                HashMap<String, Object> subMap = new HashMap<>(8);
                map.put(key, subMap);
                buildJson(subMap, path.substring(idx + 1), value);
            }
        } else {
            map.put(path, value);
        }
    }

    public static JsonNode toJsonNode(Object value) {
        return from(JsonUtils.toString(value), JsonNode.class);
    }

    /**
     * 格式化离线内容
     * @param object    待格式化的内容对象
     * @return  格式化后的字符串内容
     */
    public static String toStringFormat(Object object) {
        ObjectMapper mapper = new ObjectMapper();
        try {
            return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(object);
        } catch (JsonProcessingException e) {
            throw new AmapException(AmapExceptionCode.COMMON_SERVER_ERROR, "格式化离线内容异常", e);
        }
    }
}
